home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / lockdir / lockdir.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-28  |  4.1 KB  |  159 lines

  1. /***********************************************************************
  2.  *
  3.  *    Copyright (c) Berkeley Softworks 1989 -- All Rights Reserved
  4.  *
  5.  * PROJECT:      PCGEOS
  6.  * MODULE:      Tools/lockdir -- atomic directory lock acquisition
  7.  * FILE:      lockdir.c
  8.  *
  9.  * AUTHOR:        Adam de Boor: Sep 17, 1989
  10.  *
  11.  * REVISION HISTORY:
  12.  *    Date      Name        Description
  13.  *    ----      ----        -----------
  14.  *    9/17/89      ardeb        Initial version
  15.  *
  16.  * DESCRIPTION:
  17.  *    Simple program to acquire a lock on a directory. Waits
  18.  *    for up to 10 minutes before giving up. Exits 0 if the lock acquired
  19.  *    and non-zero otherwise.
  20.  *
  21.  *    If no argument is given, this assumes it's in the proper directory.
  22.  *
  23.  *    To obtain the lock, we create a temporary file that we attempt
  24.  *    to link to the lock file, since NFS does have an atomic link
  25.  *    operation.
  26.  *
  27.  *    Usage: lockdir [<lockfile name>]
  28.  *
  29.  ***********************************************************************/
  30. #ifndef lint
  31. static char *rcsid =
  32. "$Id: lockdir.c,v 1.4 89/10/10 01:16:02 adam Exp $";
  33. #endif lint
  34.  
  35. #include    <stdio.h>
  36. #include    <stdlib.h>
  37. #include    <sys/file.h>
  38. #include    <sys/signal.h>
  39. #include    <pwd.h>
  40. #include    <setjmp.h>
  41.  
  42. #define MAX_TRIES   60        /* Maximum number of times to try and create
  43.                  * the lock file */
  44. #define SLEEP_FOR   5        /* Number of seconds to sleep between tries */
  45.  
  46. jmp_buf        interrupt;
  47.  
  48. irq() { longjmp(interrupt, 1); }
  49.  
  50. extern char *getlogin();
  51.  
  52. main(argc, argv)
  53.     int        argc;
  54.     char    **argv;
  55. {
  56.     int                i;            /* Attempt counter */
  57.     char            *lockfile;    /* File we want to get */
  58.     char            *tempfile;    /* Temp file from which we link */
  59.     char            *cp;        /* One past last char wanted in lockfile when
  60.                  * creating the template */
  61.     int                fd;            /* Stream open to temporary file */
  62.     char            host[64];    /* Current host's name */
  63.     char            *user;      /* User's login name */
  64.     char            buf[128];    /* String to write to lock file */
  65.  
  66.     /*
  67.      * We only allow interrupts while we're sleeping, otherwise we may leave
  68.      * a lockfile around we don't want to.
  69.      */
  70.     signal(SIGINT, SIG_IGN);
  71.     signal(SIGTERM, SIG_IGN);
  72.  
  73.     /*
  74.      * Figure the name of the lock file.
  75.      */
  76.     if (argc == 1) {
  77.     lockfile = "LOCK";
  78.     } else {
  79.     lockfile=argv[1];
  80.     }
  81.  
  82.     /*
  83.      * From the lock file, create a template for mkstemp that is any
  84.      * leading path components followed by six X's, to contain the process
  85.      * ID and a letter.
  86.      */
  87.     cp = (char *)rindex(lockfile, '/');
  88.     if (cp++ == NULL) {
  89.     cp = lockfile;
  90.     }
  91.     tempfile = (char *)malloc(cp-lockfile + 7);
  92.     sprintf(tempfile, "%.*sXXXXXX", cp-lockfile, lockfile);
  93.  
  94.     fd = mkstemp(tempfile);
  95.  
  96.     if (fd < 0) {
  97.     printf("Couldn't create temp file \"%s\"\n", tempfile);
  98.     exit(1);
  99.     }
  100.  
  101.     /*
  102.      * Place user@host into the file, then close it.
  103.      */
  104.     user = getlogin();
  105.     if (user == NULL) {
  106.     struct passwd *pwd = getpwuid(getuid());
  107.  
  108.     if (pwd != NULL) {
  109.         user = pwd->pw_name;
  110.     } else {
  111.         user = "?";
  112.     }
  113.     }
  114.  
  115.     gethostname(host, sizeof(host));
  116.     sprintf(buf, "%s@%s", user, host);
  117.     write(fd, buf, strlen(buf)+1);
  118.     (void)close(fd);
  119.     
  120.     /*
  121.      * Now try and link the temp file to the lock file. If it succeeds,
  122.      * we've got the lock. Else we need to sleep for a bit.
  123.      */
  124.     if (setjmp(interrupt) == 0) {
  125.     for (i = MAX_TRIES; i > 0; i--) {
  126.         if (link(tempfile, lockfile) < 0) {
  127.         signal(SIGINT, irq);
  128.         signal(SIGTERM, irq);
  129.         
  130.         /*
  131.          * See who has the thing locked and tell the user about it.
  132.          * Note that if we can't open the file, we immediately try for
  133.          * the lock again.
  134.          */
  135.         fd = open(lockfile, O_RDONLY, 0);
  136.         if (fd >= 0) {
  137.             (void)read(fd, buf, sizeof(buf));
  138.             printf("locked by %s. Sleeping for %d seconds...",
  139.                buf, SLEEP_FOR);
  140.             fflush(stdout);
  141.             sleep(SLEEP_FOR);
  142.         }
  143.         
  144.         signal(SIGINT, SIG_IGN);
  145.         signal(SIGTERM, SIG_IGN);
  146.         } else {
  147.         /*
  148.          * Remove the temporary file, since the lockfile now points to
  149.          * the file with the user and hostname.
  150.          */
  151.         unlink(tempfile);
  152.         exit(0);
  153.         }
  154.     }
  155.     }
  156.     unlink(tempfile);
  157.     exit(1);
  158. }
  159.